#ifndef	__CXX_VIEWS_GRPH_CANVAS_IMPL_H__
#define	__CXX_VIEWS_GRPH_CANVAS_IMPL_H__

#include "pen_impl.h"
#include "bitmap_impl.h"
#include "fontmgr_impl.h"

#include "agg/pixel_formats.h"
#include "agg/agg_renderer_mclip.h"
#include "agg/pixfmt_rgb24_lcd.h"
#include "agg/agg_renderer_scanline.h"

namespace visgrph
{

class pen_impl;
class bitmap_impl;
typedef agg::renderer_mclip<pixfmt>	renderer_mclip;

#ifdef AGG_RGB565
	typedef agg::pixfmt_rgb565 pixfmt_type;
	typedef	agg::pixfmt_rgb565_lcd pixfmt_type_lcd;
#endif
#ifdef AGG_RGBA32
	typedef agg::pixfmt_rgba32 pixfmt_type;
	typedef	agg::pixfmt_rgba32_lcd pixfmt_type_lcd;
#endif
#ifdef AGG_BGRA32
	typedef agg::pixfmt_bgra32 pixfmt_type;
	typedef	agg::pixfmt_bgra32_lcd pixfmt_type_lcd;
#endif

typedef	agg::renderer_mclip<pixfmt_type_lcd> base_ren_type_lcd;
typedef agg::renderer_scanline_aa_solid<base_ren_type_lcd> renderer_solid_lcd;
typedef agg::lcd_distribution_lut lcd_distribution_lut;
typedef agg::font_engine_freetype_int32 font_engine_type;
typedef font_engine_type::path_adaptor_type path_adaptor_type;

class canvas_impl
{
public:
	canvas_impl() : m_target(NULL) {}
	canvas_impl(const canvas_impl& c);
	canvas_impl(const canvas_impl& c, int dx, int dy, int w, int h)
		: m_target(NULL)
	{
		attach(const_cast<canvas_impl&>(c), dx, dy, w, h);
	}

	canvas_impl(bitmap_impl* bi)
		: m_target(NULL)
	{
		if (!bi) return;
		attach(bi, 0, 0, bi->width(), bi->height());
	}

	canvas_impl(bitmap_impl* bi, int dx, int dy, int w, int h)
		: m_target(NULL)
	{
		if (!bi) return;
		attach(bi, dx, dy, w, h);
	}

	~canvas_impl()
	{
		if (m_target)
		{

			m_target->release();
			m_target = NULL;
		}
	}

	// attach the whole area of a specific bitmap
	bool attach(bitmap_impl* target, int dx, int dy, int w, int h);
	bool attach(canvas_impl& c, int dx, int dy, int w, int h);

public:
	// gets
	int width(void) const {
		return m_rmc.width();
	}

	int height(void) const {
		return m_rmc.height();
	}

public:
	// clear
	void clear(color c);

	// easy functions
	void hline(uint x, uint y, uint length, color c);
	void vline(uint x, uint y, uint height, color c);

	void rectangle(uint x, uint y, uint width, uint height, color c);

	void line(float x1, float y1, float x2, float y2);

	// text drawing methods
	bool textout(float x, float y, formatted_text_impl* fti, color c, uint sz);

public:
	// functions for select object
	void select_object(pen_impl& pen) {
		m_pen = pen;
	}

public:
	// clip
	void reset_clipping(void) {
		m_rmc.reset_clipping(false);
		m_ren_base_lcd.reset_clipping(false);
	}
	
	bool add_clipbox(int left, int top, int width, int height) {
		if (width <= 0 || height <= 0)
			return false;
		m_rmc.add_clip_box(left, top, left + width - 1, top + height - 1);
		m_ren_base_lcd.add_clip_box(left * f_subpixel_scale,
			top, (left + width - 1) * f_subpixel_scale, top + height - 1);
		return true;
	}

	bool add_clipbox(const rect& r) {
		if (r.width <= 0 || r.height <= 0)
			return false;
		m_rmc.add_clip_box(r.left, r.top, r.left + r.width - 1, r.top + r.height - 1);
		m_ren_base_lcd.add_clip_box(r.left, r.top, r.left + r.width - 1, r.top + r.height - 1);
		return true;
	}

	void remove_last_clipbox(void) {
		m_rmc.remove_last_clip_box();
		m_ren_base_lcd.remove_last_clip_box();
	}

private:
	void draw_line(float x1, float y1, float x2, float y2);
	void drawtext(float _x, float _y, formatted_text_impl* fti, const char* str, color c, int sz);

	bool draw_formattedtext(float x, float y, formatted_text_impl* fti,
		color c, uint line_start, uint line_end);

	// font: check rect validity
	bool check_rect(rect& r);

	// check for actual draw row range of font
	bool get_actual_row_range(float y, formatted_text_impl* fti, uint lines, uint& start, uint& end);

	bool set_textclip(int x, int y, formatted_text_impl* fti, agg::rect_i& bounds,
		agg::pod_bvector<agg::rect_i, 4>& dup);
	bool clear_textclip(formatted_text_impl* fti, const agg::rect_i& bounds,
		agg::pod_bvector<agg::rect_i, 4>& dup);

private:
	pen_impl				m_pen;

	agg::rendering_buffer	m_rbuf;
	pixfmt					m_pf;
	renderer_mclip			m_rmc;

	pixfmt_type_lcd			m_pf_lcd;
	base_ren_type_lcd		m_ren_base_lcd;
	renderer_solid_lcd		m_ren_solid_lcd;

	bitmap_impl*			m_target;
};

};	// namespace visgrph

#endif	// __CXX_VIEWS_GRPH_CANVAS_IMPL_H__
/* EOF */

